#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include "err.hpp"
#include "Task.hpp"
#include "Thread.hpp"
#include "threadPool_V4.hpp"
#include "Log.hpp"
#include "Daemon.hpp"

// V6版本（最终版）：
// 功能：基于线程池的多人聊天室
// 核心：守护进程化，在后台持续运行

namespace ns_server
{
    class TcpServer
    {
        static const uint16_t default_port = 8080;
        static const int backlog = 32; // TODO
    public:
        TcpServer(uint16_t port = default_port)
            : port_(port), quit_(true)
        {
        }

        ~TcpServer()
        {
        }

        void InitServer()
        {
            // 初始化服务器
            listen_sock_ = socket(AF_INET, SOCK_STREAM, 0); // 基于IPV4的流式数据传输
            if (listen_sock_ == -1)
            {
                logMessage(Fatal, "Create Sock Fail:  %s", strerror(errno));
                exit(SOCKET_ERR);
            }
            logMessage(Info, "Create Sock Success:  %s", strerror(errno));

            // 创建addr结构体（包含自己的端口号和IP信息）
            struct sockaddr_in local;
            memset(&local, 0, sizeof local);
            local.sin_family = AF_INET;
            local.sin_port = htons(port_);
            local.sin_addr.s_addr = INADDR_ANY; // 可以绑定任意ip

            // 绑定
            if (bind(listen_sock_, (struct sockaddr *)&local, sizeof local) == -1)
            {
                logMessage(Fatal, "Bind Sock Fail:  %s", strerror(errno));
                exit(BIND_ERR);
            }
            logMessage(Info, "Bind Sock Success:  %s", strerror(errno));

            // 监听
            if (listen(listen_sock_, backlog) == -1)
            {
                logMessage(Fatal, "Listen Sock Fail:  %s", strerror(errno));
                exit(LISTEN_ERR);
            }
            logMessage(Info, "Listen Sock Success:  %s", strerror(errno));

            logMessage(Info, "Socket Bind Listen success!");

            //初始化成功后，成为守护进程
            Daemon();
        }

        void service(const int &sock, const std::string &clientip, const uint16_t &clientport)
        {
            // 流式数据传输，可以使用文件操作相关接口

            // 处理数据（打印）
            std::string who = "Client [" + clientip + "-" + std::to_string(clientport) + "]";

            char buff[1024];
            while (true)
            {
                // 从客户端读取数据
                int n = read(sock, buff, sizeof(buff) - 1);
                if (n > 0)
                {
                    buff[n] = '\0';

                    std::cout << who << " >>" << buff << std::endl;

                    // 回响数据
                    write(sock, buff, strlen(buff));
                }
                else if (n == 0)
                {
                    // 写端关闭，读到0了
                    logMessage(Info, "%s quit, Me too", who.c_str());
                    break;
                }
                else
                {
                    // 读取异常
                    logMessage(Error, "Read Error: %s", strerror(errno));
                    break;
                }
            }

            close(sock);
            logMessage(Debug, "Close sock");
        }

        void StartServer()
        {
            quit_ = false; // 服务器运行，不退出
            while (!quit_)
            {
                // 连接
                struct sockaddr_in client; // 客户端信息
                socklen_t len = sizeof(client);
                int sock = accept(listen_sock_, (struct sockaddr *)&client, &len);
                if (sock == -1)
                {
                    logMessage(Fatal, "Accept Sock Fail: %s", strerror(errno));
                    exit(ACCEPT_ERR);
                }
                logMessage(Info, "Link Success! %d from %d", sock, listen_sock_);

                std::string clientip = inet_ntoa(client.sin_addr);
                uint16_t clientport = ntohs(client.sin_port);

                Task t(sock, clientip, clientport, std::bind(&TcpServer::service, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
                // 调用单例对象，将线程塞入线程池中
                ThreadPool<Task>::GetInstace()->pushTask(t);
            }
        }

    private:
        int listen_sock_; // 监听套接字
        uint16_t port_;   // 端口号
        bool quit_;       // 退出状态
    };
}